#include "Interface.h"
#include <ncurses.h>
#include "locale.h"
#include <thread>
#include "unistd.h"
#include <iostream>
#include <openssl/sha.h>
#include <iomanip>
#include <sstream>

// 将字节数组转换为十六进制字符串
std::string bytes_to_hex_string(const unsigned char* bytes, size_t length) {
    std::ostringstream oss;
    for (size_t i = 0; i < length; ++i) {
        oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(bytes[i]);
    }
    return oss.str();
}

// 对密码进行SHA-256哈希加密
std::string hash_password(const std::string& password) {
    unsigned char hash[SHA256_DIGEST_LENGTH]; // 存储哈希结果

    // 计算SHA-256哈希值
    SHA256(reinterpret_cast<const unsigned char*>(password.c_str()), password.size(), hash);

    // 转换为十六进制字符串
    return bytes_to_hex_string(hash, SHA256_DIGEST_LENGTH);
}

struct InterfacePrivate
{
    //界面指针
    WINDOW *win;
    int startx, starty;
};

Interface::Interface():p(new InterfacePrivate)
{
    setlocale(LC_ALL, ""); //设置支持本地系统语言
    initscr();
}

Interface::~Interface()
{
    delete p;
    endwin();
}

void Interface::clear()
{
    refresh();
    //指针释放
    delwin(p->win);
    p->win = nullptr;
}

void Interface::drawBox(int width, int height)
{
    p->starty = (LINES - height) / 2;  // 计算居中位置
    p->startx = (COLS - width) / 2;
    p->win = newwin(height, width, p->starty, p->startx);
    
    box(p->win, 0, 0);
    wrefresh(p->win);
}

void Interface::drawText(int x, int y, const std::string &text)
{
    mvwprintw(p->win, y, x, "%s", text.c_str());
    wrefresh(p->win);
}


void Interface::EnableKeyboard(bool enable)
{
    keypad(p->win, enable);
}

void Interface::ShowCursor(bool show)
{
    curs_set(show);
}

std::string Interface::GetInput(int x, int y)
{
    char buffer[256];
    mvwgetnstr(p->win, y, x, buffer, 255);
    wrefresh(p->win);

    return std::string(buffer);
}

std::string Interface::GetPassword(int x, int y)
{
    int index = 0;
    char ch;
    char password[256];
    wmove(p->win, y, x);
    while ((ch = wgetch(p->win)) != '\n' && index < 255) {
        if (ch == KEY_BACKSPACE || ch == 127) 
        { 
            // 处理退格键
            if (index > 0) 
            {
                index--;
            }
            mvwaddch(p->win, y, x + index, ' '); // 清除当前位置
            mvwaddch(p->win, y, x + index+1, ' '); 
            mvwaddch(p->win, y, x + index+2, ' '); // 清除多余字符
            wmove(p->win, y, x + index);
            
        } else {
            password[index++] = ch;
            mvwaddch(p->win, y, x + index, ' '); // 清除当前位置
            // 显示星号而不是实际字符
            mvwaddch(p->win, y,x + index - 1, '*');
        }
        wrefresh(p->win);

    }
    password[index] = '\0'; // 添加字符串结束符
    return std::string(password);
}

void Interface::KeyboardEvent(const std::function<void(int)> &callback)
{
    
    int ch = '\n';
    while ( (ch = wgetch(p->win)) != '\n')
    {
        callback(ch);
    }
}


void homepage(UserOperationsProxy& proxy){
    Interface i;
    i.clear();
    i.drawBox(40,10);
    i.drawText(15,1,"主页");
    i.drawText(5,2,"-> 登录");
    i.drawText(25,2,"  注册");
    i.ShowCursor(false);
    i.EnableKeyboard(true);
    int choice = 0;
    i.KeyboardEvent([&i,&choice](int key)
    {
        switch (key) 
        {
            case Interface::Keyboard::Key_left:
            {
                choice = (choice - 1 + 2) % 2;
                break;
            }
            case Interface::Keyboard::Key_right:
            {
                choice = (choice + 1) % 2;
                break;
            }
            case Interface::Keyboard::Key_esc:
            {
                exit(1);
            }
        }
        i.drawText(5,2,(choice == 0) ? "-> 登录" : "   登录");
        i.drawText(25,2,(choice == 1) ? "-> 注册" : "   注册");
    });
    if(choice == 0) //LOGIN 
    {  
      CreateLoginInterface(proxy);
    }else{
      CreateRegisterface(proxy);
    }
}
void CreateLoginInterface(UserOperationsProxy& proxy)
{
    Interface i;
    initscr();
    i.drawBox(40,10);
    i.drawText(15,1,"登陆界面");
    i.drawText(2,3,"用户名:");
    i.drawText(2,5,"密码:");
    i.drawText(5,7,"   登陆");
    i.drawText(25,7,"   退出");

    auto Name =  i.GetInput(10,3);
    auto passwd = i.GetPassword(10,5);

    i.drawText(5,7,"-> 登陆");
    i.drawText(25,7,"   退出");
    i.ShowCursor(false);
    i.EnableKeyboard(true);
    int choice = 0;
    i.KeyboardEvent([&i,&choice](int key)
    {
        switch (key) 
        {
            case Interface::Keyboard::Key_left:
            {
                choice = (choice - 1 + 2) % 2;
                break;
            }
            case Interface::Keyboard::Key_right:
                choice = (choice + 1) % 2;
                break;
        }
        i.drawText(5,7,(choice == 0) ? "-> 登陆" : "   登陆");
        i.drawText(25,7,(choice == 1) ? "-> 退出" : "   退出");
    });

    if(choice == 0)
    {               // 弹出提示窗口
        std::string hashed_password = hash_password(passwd);
      if(proxy.loginUser(Name,hashed_password)){
                i.drawText(15,8,"登录中...");
                i.clear();
                return ;
       }else{

        i.drawText(15,8,"用户不存在");
        sleep(2);
        i.clear();
        CreateLoginInterface(proxy);
        return ;
       }
    }
    sleep(2);
    i.clear();
    homepage(proxy);
    return ;
}

void CreateRegisterface(UserOperationsProxy& proxy)
{
    Interface i;
    initscr();
    i.drawBox(40,10);
    i.drawText(15,1,"注册界面");
    i.drawText(2,3,"用户名:");
    i.drawText(2,5,"密码:");
    i.drawText(5,7,"   注册");
    i.drawText(25,7,"   退出");

    auto Name =  i.GetInput(10,3);
    auto passwd = i.GetPassword(10,5);

    i.drawText(5,7,"->注册");
    i.drawText(25,7,"   退出");
    i.ShowCursor(false);
    i.EnableKeyboard(true);
    int choice = 0;
    i.KeyboardEvent([&i,&choice](int key)
    {
        switch (key) 
        {
            case Interface::Keyboard::Key_left:
            {
                choice = (choice - 1 + 2) % 2;
                break;
            }
            case Interface::Keyboard::Key_right:
                choice = (choice + 1) % 2;
                break;
        }
        i.drawText(5,7,(choice == 0) ? "-> 注册" : "   注册");
        i.drawText(25,7,(choice == 1) ? "-> 退出" : "   退出");
    });

    if(choice == 0) //LOGIN 
    {        
               // 弹出提示窗口
      if(proxy.ifUser(Name)){
                i.drawText(15,3,"用户已存在");
                sleep(2);
                i.clear();
                homepage(proxy);
                return ;
       }else{
            std::string hashed_password = hash_password(passwd);
            User user(Name,hashed_password);
            proxy.registerUser(user);
            i.drawText(15,8,"注册成功");
            i.clear();
            sleep(2);
            homepage(proxy);
            return;
       }
            
      
    }
    else
    {
        homepage(proxy);
    }
    sleep(2);
    i.clear();
    return ;
}
